#include "header/pyramid_terasse.h"

OSG_USING_NAMESPACE

double pyraTe_height = 2500;
double pyraTe_width = 2500;
double pyraTe_door_height_begin = 100;
double terasse_width = 1100;			// +100
double terasse_depth = 550;				// +50
double zaun_height = 100;


NodePtr createTerasse() {
	
	Matrix m;
	float winkel = tan(M_PI/2-atan(pyraTe_height/(pyraTe_width/2)));
	
	
	
	// *********** Terrasse ***********
	NodePtr terrasse = makeBox(terasse_width, pyraTe_door_height_begin, terasse_depth, 100, 100, 10);
	
	TransformPtr tterrasse = Transform::create();
	beginEditCP(tterrasse, Transform::MatrixFieldMask);
		m.setIdentity();
		m.setTranslate(pyraTe_width/2, pyraTe_door_height_begin/2, terasse_depth/2+pyraTe_width-winkel*pyraTe_door_height_begin);
		tterrasse->setMatrix(m);
	endEditCP(tterrasse, Transform::MatrixFieldMask);
	
	NodePtr terrasseTrans = Node::create();
	beginEditCP(terrasseTrans, Node::CoreFieldMask | Node::ChildrenFieldMask);
		terrasseTrans->setCore(tterrasse);
		terrasseTrans->addChild(terrasse);
	endEditCP(terrasseTrans, Node::CoreFieldMask | Node::ChildrenFieldMask);

	
	//Kammer Boden Texturen laden
	ImagePtr cryptterrasseImage = Image::create();
   cryptterrasseImage->read("materials/sand.jpg");    
	    
	    
	//Aus dem Bild eine Textur machen
	TextureChunkPtr cryptterrasseTex = TextureChunk::create();
	beginEditCP(cryptterrasseTex);
		cryptterrasseTex->setImage(cryptterrasseImage);
		cryptterrasseTex->setMinFilter(GL_LINEAR);
		cryptterrasseTex->setMagFilter(GL_LINEAR);
		cryptterrasseTex->setWrapS(GL_REPEAT);
		cryptterrasseTex->setWrapT(GL_REPEAT);
		cryptterrasseTex->setEnvMode(GL_MODULATE);
	endEditCP(cryptterrasseTex);
	  
	SimpleMaterialPtr cryptterrasseMat = SimpleMaterial::create();
	beginEditCP(cryptterrasseMat);
		//Materialfarbe bei seitlicher Ansicht (Brechungswinkel)
		cryptterrasseMat->setAmbient(Color3f(0.3, 0.3, 0.3));    
		//Bestimmt Farbe des Materials
		cryptterrasseMat->setDiffuse(Color3f(1.0, 1.0, 1.0));
		cryptterrasseMat->addChunk(cryptterrasseTex);
	endEditCP(cryptterrasseMat);

	//Mittelpunkt des Texturtraegers heraus finden und die Textur darauf legen.
	GeometryPtr cryptterrasseGeo = GeometryPtr::dcast(terrasse->getCore());
	beginEditCP(cryptterrasseGeo);
		cryptterrasseGeo->setMaterial(cryptterrasseMat);
	endEditCP(cryptterrasseGeo);
	//Ende Boden Textur
	
	
	
	
	
	
	// *********** ZaunM ***********
	GeometryPtr zaunMGeo = makePlaneGeo(terasse_width-100, zaun_height, 10, 10);
	
	//Load the image we want to use as a texture  
	ImagePtr zaunImage = Image::create();
	zaunImage->read("materials/zaun2-lang.png");
	
	//now we create the texture that will hold the image
	SimpleTexturedMaterialPtr zaunTex = SimpleTexturedMaterial::create();
	beginEditCP(zaunTex);
		zaunTex->setImage(zaunImage);
	endEditCP(zaunTex);
	
	//now assign the fresh texture to the geometry
	beginEditCP(zaunMGeo, Geometry::MaterialFieldMask);
		zaunMGeo->setMaterial(zaunTex);
	endEditCP(zaunMGeo, Geometry::MaterialFieldMask);
	
	// Create the node that will hold our geometry
	NodePtr zaunM = Node::create();
	beginEditCP(zaunM, Node::CoreFieldMask);
		zaunM->setCore(zaunMGeo);
	endEditCP(zaunM, Node::CoreFieldMask);
	
	TransformPtr tzaunM = Transform::create();
	beginEditCP(tzaunM, Transform::MatrixFieldMask);
		m.setIdentity();
		m.setTranslate(pyraTe_width/2,
				  pyraTe_door_height_begin+zaun_height/2,
				  terasse_depth-50+pyraTe_width-winkel*pyraTe_door_height_begin);
		tzaunM->setMatrix(m);
	endEditCP(tzaunM, Transform::MatrixFieldMask);
	
	NodePtr zaunMTrans = Node::create();
	beginEditCP(zaunMTrans, Node::CoreFieldMask | Node::ChildrenFieldMask);
		zaunMTrans->setCore(tzaunM);
		zaunMTrans->addChild(zaunM);
	endEditCP(zaunMTrans, Node::CoreFieldMask | Node::ChildrenFieldMask);
	
	
	// *********** ZaunL ***********
	GeometryPtr zaunLGeo = makePlaneGeo(terasse_depth-50+winkel*zaun_height, zaun_height, 10, 10);
	
	//Load the image we want to use as a texture
	ImagePtr zaunSImage = Image::create();
	zaunSImage->read("materials/zaun2-kurz.png");
	
	//now we create the texture that will hold the image
	SimpleTexturedMaterialPtr zaunSTex = SimpleTexturedMaterial::create();
	beginEditCP(zaunSTex);
		zaunSTex->setImage(zaunSImage);
	endEditCP(zaunSTex);
	
	//now assign the fresh texture to the geometry
	beginEditCP(zaunLGeo, Geometry::MaterialFieldMask);
		zaunLGeo->setMaterial(zaunSTex);
	endEditCP(zaunLGeo, Geometry::MaterialFieldMask);
	
	// Create the node that will hold our geometry
	NodePtr zaunL = Node::create();
	beginEditCP(zaunL, Node::CoreFieldMask);
		zaunL->setCore(zaunLGeo);
	endEditCP(zaunL, Node::CoreFieldMask);
	
	TransformPtr tzaunL = Transform::create();
	beginEditCP(tzaunL, Transform::MatrixFieldMask);
		m.setIdentity();
		m.setTranslate(pyraTe_width/2+(terasse_width-100)/2,
				  pyraTe_door_height_begin+zaun_height/2,
				  pyraTe_width+terasse_depth-50-(terasse_depth-50+winkel*zaun_height)/2-winkel*pyraTe_door_height_begin);
		m.setRotate(Quaternion(Vec3f(0,1,0), M_PI/2));
		tzaunL->setMatrix(m);
	endEditCP(tzaunL, Transform::MatrixFieldMask);
	
	NodePtr zaunLTrans = Node::create();
	beginEditCP(zaunLTrans, Node::CoreFieldMask | Node::ChildrenFieldMask);
		zaunLTrans->setCore(tzaunL);
		zaunLTrans->addChild(zaunL);
	endEditCP(zaunLTrans, Node::CoreFieldMask | Node::ChildrenFieldMask);
	
	
	// *********** ZaunR ***********
	GeometryPtr zaunRGeo = makePlaneGeo(terasse_depth-50+winkel*zaun_height, zaun_height, 10, 10);
	
	//now assign the fresh texture to the geometry
	beginEditCP(zaunRGeo, Geometry::MaterialFieldMask);
		zaunRGeo->setMaterial(zaunSTex);
	endEditCP(zaunRGeo, Geometry::MaterialFieldMask);
	
	// Create the node that will hold our geometry
	NodePtr zaunR = Node::create();
	beginEditCP(zaunR, Node::CoreFieldMask);
		zaunR->setCore(zaunRGeo);
	endEditCP(zaunR, Node::CoreFieldMask);
	
	TransformPtr tzaunR = Transform::create();
	beginEditCP(tzaunR, Transform::MatrixFieldMask);
		m.setIdentity();
		m.setTranslate(pyraTe_width/2-(terasse_width-100)/2,
				  pyraTe_door_height_begin+zaun_height/2,
				  pyraTe_width+terasse_depth-50-(terasse_depth-50+winkel*zaun_height)/2-winkel*pyraTe_door_height_begin);
		m.setRotate(Quaternion(Vec3f(0,1,0), M_PI/2));
		tzaunR->setMatrix(m);
	endEditCP(tzaunR, Transform::MatrixFieldMask);
	
	NodePtr zaunRTrans = Node::create();
	beginEditCP(zaunRTrans, Node::CoreFieldMask | Node::ChildrenFieldMask);
		zaunRTrans->setCore(tzaunR);
		zaunRTrans->addChild(zaunR);
	endEditCP(zaunRTrans, Node::CoreFieldMask | Node::ChildrenFieldMask);
	
	
	// *********** ZaunPfostenL ***********
	GeometryPtr zaunPfostenLGeo = makeCylinderGeo(zaun_height+4, 5, 40, true, true, true);
	
	//Load the image we want to use as a texture
	ImagePtr zaunPfostenImage = Image::create();
	zaunPfostenImage->read("materials/wood.jpg");
	
	//now we create the texture that will hold the image
	SimpleTexturedMaterialPtr zaunPfostenTex = SimpleTexturedMaterial::create();
	beginEditCP(zaunPfostenTex);
		zaunPfostenTex->setImage(zaunPfostenImage);
	endEditCP(zaunPfostenTex);
	
	//now assign the fresh texture to the geometry
	beginEditCP(zaunPfostenLGeo, Geometry::MaterialFieldMask);
		zaunPfostenLGeo->setMaterial(zaunPfostenTex);
	endEditCP(zaunPfostenLGeo, Geometry::MaterialFieldMask);
	
	// Create the node that will hold our geometry
	NodePtr zaunPfostenL = Node::create();
	beginEditCP(zaunPfostenL, Node::CoreFieldMask);
		zaunPfostenL->setCore(zaunPfostenLGeo);
	endEditCP(zaunPfostenL, Node::CoreFieldMask);
	
	TransformPtr tzaunPfostenL = Transform::create();
	beginEditCP(tzaunPfostenL, Transform::MatrixFieldMask);
		m.setIdentity();
		m.setTranslate(pyraTe_width/2+(terasse_width-100)/2,
				  pyraTe_door_height_begin+zaun_height/2,
				  pyraTe_width+terasse_depth-50-winkel*pyraTe_door_height_begin);
		m.setRotate(Quaternion(Vec3f(0,1,0), M_PI/2));
		tzaunPfostenL->setMatrix(m);
	endEditCP(tzaunPfostenL, Transform::MatrixFieldMask);
	
	NodePtr zaunPfostenLTrans = Node::create();
	beginEditCP(zaunPfostenLTrans, Node::CoreFieldMask | Node::ChildrenFieldMask);
		zaunPfostenLTrans->setCore(tzaunPfostenL);
		zaunPfostenLTrans->addChild(zaunPfostenL);
	endEditCP(zaunPfostenLTrans, Node::CoreFieldMask | Node::ChildrenFieldMask);
	
	
	// *********** ZaunPfostenR ***********
	GeometryPtr zaunPfostenRGeo = makeCylinderGeo(zaun_height+4, 5, 40, true, true, true);
	
	//now assign the fresh texture to the geometry
	beginEditCP(zaunPfostenRGeo, Geometry::MaterialFieldMask);
		zaunPfostenRGeo->setMaterial(zaunPfostenTex);
	endEditCP(zaunPfostenRGeo, Geometry::MaterialFieldMask);
	
	// Create the node that will hold our geometry
	NodePtr zaunPfostenR = Node::create();
	beginEditCP(zaunPfostenR, Node::CoreFieldMask);
		zaunPfostenR->setCore(zaunPfostenRGeo);
	endEditCP(zaunPfostenR, Node::CoreFieldMask);
	
	TransformPtr tzaunPfostenR = Transform::create();
	beginEditCP(tzaunPfostenR, Transform::MatrixFieldMask);
		m.setIdentity();
		m.setTranslate(pyraTe_width/2-(terasse_width-100)/2,
				  pyraTe_door_height_begin+zaun_height/2,
				  pyraTe_width+terasse_depth-50-winkel*pyraTe_door_height_begin);
		m.setRotate(Quaternion(Vec3f(0,1,0), M_PI/2));
		tzaunPfostenR->setMatrix(m);
	endEditCP(tzaunPfostenR, Transform::MatrixFieldMask);
	
	NodePtr zaunPfostenRTrans = Node::create();
	beginEditCP(zaunPfostenRTrans, Node::CoreFieldMask | Node::ChildrenFieldMask);
		zaunPfostenRTrans->setCore(tzaunPfostenR);
		zaunPfostenRTrans->addChild(zaunPfostenR);
	endEditCP(zaunPfostenRTrans, Node::CoreFieldMask | Node::ChildrenFieldMask);
	
   


	
	
	
	/******************************
	 * Pillars in front of the pyramid with roof
	 * ***************************/


	NodePtr pyramidPillarLeft = makeCylinder( 300, 15, 8, true, true, true );
	
	TransformPtr tpyramidPillarLeft = Transform::create();
	beginEditCP(tpyramidPillarLeft, Transform::MatrixFieldMask);
		m.setIdentity();
		m.setTranslate(1150,150, 2500);
		tpyramidPillarLeft->setMatrix(m);
	endEditCP(tpyramidPillarLeft, Transform::MatrixFieldMask);
	
	NodePtr pyramidPillarLeftTrans = Node::create();
	beginEditCP(pyramidPillarLeftTrans, Node::CoreFieldMask | Node::ChildrenFieldMask);
		pyramidPillarLeftTrans->setCore(tpyramidPillarLeft);
		pyramidPillarLeftTrans->addChild(pyramidPillarLeft);
	endEditCP(pyramidPillarLeftTrans, Node::CoreFieldMask | Node::ChildrenFieldMask);
	
	
	NodePtr pyramidPillarRight = makeCylinder( 300, 15, 8, true, true, true );
	
	TransformPtr tpyramidPillarRight = Transform::create();
	beginEditCP(tpyramidPillarRight, Transform::MatrixFieldMask);
		m.setIdentity();
		m.setTranslate(1350,150, 2500);
		tpyramidPillarRight->setMatrix(m);
	endEditCP(tpyramidPillarRight, Transform::MatrixFieldMask);
	
	NodePtr pyramidPillarRightTrans = Node::create();
	beginEditCP(pyramidPillarRightTrans, Node::CoreFieldMask | Node::ChildrenFieldMask);
		pyramidPillarRightTrans->setCore(tpyramidPillarRight);
		pyramidPillarRightTrans->addChild(pyramidPillarRight);
	endEditCP(pyramidPillarRightTrans, Node::CoreFieldMask | Node::ChildrenFieldMask);

	
	
	NodePtr pyramidPillarLeftFront = makeCylinder( 300, 15, 8, true, true, true );
	
	TransformPtr tpyramidPillarLeftFront = Transform::create();
	beginEditCP(tpyramidPillarLeftFront, Transform::MatrixFieldMask);
		m.setIdentity();
		m.setTranslate(1150,150, 2700);
		tpyramidPillarLeftFront->setMatrix(m);
	endEditCP(tpyramidPillarLeftFront, Transform::MatrixFieldMask);
	
	NodePtr pyramidPillarLeftFrontTrans = Node::create();
	beginEditCP(pyramidPillarLeftFrontTrans, Node::CoreFieldMask | Node::ChildrenFieldMask);
		pyramidPillarLeftFrontTrans->setCore(tpyramidPillarLeftFront);
		pyramidPillarLeftFrontTrans->addChild(pyramidPillarLeftFront);
	endEditCP(pyramidPillarLeftFrontTrans, Node::CoreFieldMask | Node::ChildrenFieldMask);
	
	NodePtr pyramidPillarRightFront = makeCylinder( 300, 15, 8, true, true, true );
	
	TransformPtr tpyramidPillarRightFront = Transform::create();
	beginEditCP(tpyramidPillarRightFront, Transform::MatrixFieldMask);
		m.setIdentity();
		m.setTranslate(1350,150, 2700);
		tpyramidPillarRightFront->setMatrix(m);
	endEditCP(tpyramidPillarRightFront, Transform::MatrixFieldMask);
	
	NodePtr pyramidPillarRightFrontTrans = Node::create();
	beginEditCP(pyramidPillarRightFrontTrans, Node::CoreFieldMask | Node::ChildrenFieldMask);
		pyramidPillarRightFrontTrans->setCore(tpyramidPillarRightFront);
		pyramidPillarRightFrontTrans->addChild(pyramidPillarRightFront);
	endEditCP(pyramidPillarRightFrontTrans, Node::CoreFieldMask | Node::ChildrenFieldMask);


	
	//Load txtures fpr the pillar
	ImagePtr pyramidPillarImage = Image::create();
	pyramidPillarImage->read("materials/cryptWall.jpg");
		
	//Set texture options
	TextureChunkPtr pyramidPillarTex = TextureChunk::create();
		beginEditCP(pyramidPillarTex);
		pyramidPillarTex->setImage(pyramidPillarImage);
		pyramidPillarTex->setMinFilter(GL_LINEAR);
		pyramidPillarTex->setMagFilter(GL_LINEAR);
		pyramidPillarTex->setWrapS(GL_REPEAT);
		pyramidPillarTex->setWrapT(GL_REPEAT);
		pyramidPillarTex->setEnvMode(GL_MODULATE);
	endEditCP(pyramidPillarTex);
		
	
	//Set material options
	SimpleMaterialPtr pyramidPillarMat = SimpleMaterial::create();
	beginEditCP(pyramidPillarMat, SimpleMaterial::DiffuseFieldMask);
		pyramidPillarMat->setAmbient(Color3f(0.3, 0.3, 0.3));
		pyramidPillarMat->setDiffuse(Color3f(1.0, 1.0, 1.0));
		cryptterrasseMat->setSpecular(Color3f(1.0, 1.0, 1.0));
		pyramidPillarMat->setShininess(80);
		pyramidPillarMat->addChunk(pyramidPillarTex);
	endEditCP(pyramidPillarMat, SimpleMaterial::DiffuseFieldMask );
	

	//Set the material with the texture to the pillars	 
	GeometryPtr pyramidPillarGeo = GeometryPtr::dcast(pyramidPillarLeft->getCore());
	beginEditCP(pyramidPillarGeo);
		pyramidPillarGeo->setMaterial(pyramidPillarMat);
	endEditCP(pyramidPillarGeo);
		
	pyramidPillarGeo = GeometryPtr::dcast(pyramidPillarRight->getCore());
	beginEditCP(pyramidPillarGeo);
		pyramidPillarGeo->setMaterial(pyramidPillarMat);
	endEditCP(pyramidPillarGeo);
	
	pyramidPillarGeo = GeometryPtr::dcast(pyramidPillarLeftFront->getCore());
	beginEditCP(pyramidPillarGeo);
		pyramidPillarGeo->setMaterial(pyramidPillarMat);
	endEditCP(pyramidPillarGeo);
	
	pyramidPillarGeo = GeometryPtr::dcast(pyramidPillarRightFront->getCore());
	beginEditCP(pyramidPillarGeo);
		pyramidPillarGeo->setMaterial(pyramidPillarMat);
	endEditCP(pyramidPillarGeo);
		
	/***********************
	 * Roof
	 * *********************/
	
	//Defines an new NodePtr for the roof
	NodePtr pillarRoof = makeBox(270,10,400,10,10,10);
		
	TransformPtr tpillarRoof = Transform::create();
	beginEditCP(tpillarRoof, Transform::MatrixFieldMask);
		m.setIdentity();
		m.setTranslate(1250,300, 2530);
		tpillarRoof->setMatrix(m);
	endEditCP(tpillarRoof, Transform::MatrixFieldMask);
	
	NodePtr pillarPassTrans = Node::create();
	beginEditCP(pillarPassTrans, Node::CoreFieldMask | Node::ChildrenFieldMask);
		pillarPassTrans->setCore(tpillarRoof);
		pillarPassTrans->addChild(pillarRoof);
	endEditCP(pillarPassTrans, Node::CoreFieldMask | Node::ChildrenFieldMask);
	
	//Load the image for the roof
	ImagePtr pyramidPillarRoofImage = Image::create();
	pyramidPillarRoofImage->read("materials/cryptWall.jpg");
		
	//Edit the texture options
	TextureChunkPtr pyramidPillarRoofTex = TextureChunk::create();
	beginEditCP(pyramidPillarRoofTex);
		pyramidPillarRoofTex->setImage(pyramidPillarRoofImage);
		pyramidPillarRoofTex->setMinFilter(GL_LINEAR);
		pyramidPillarRoofTex->setMagFilter(GL_LINEAR);
		pyramidPillarRoofTex->setWrapS(GL_REPEAT);
		pyramidPillarRoofTex->setWrapT(GL_REPEAT);
		pyramidPillarRoofTex->setEnvMode(GL_MODULATE);
	endEditCP(pyramidPillarRoofTex);
		
	//Edit the material options
	SimpleMaterialPtr pyramidPillarRoofMat = SimpleMaterial::create();
	beginEditCP(pyramidPillarRoofMat, SimpleMaterial::DiffuseFieldMask);
		pyramidPillarRoofMat->setDiffuse(Color3f(1.0, 1.0, 1.0));
		pyramidPillarRoofMat->setAmbient(Color3f(1.0, 1.0, 1.0));
		pyramidPillarRoofMat->setSpecular(Color3f(1.0, 1.0, 1.0));
		pyramidPillarRoofMat->setShininess(0.7);
	pyramidPillarRoofMat->addChunk(pyramidPillarRoofTex);
	endEditCP(pyramidPillarRoofMat, SimpleMaterial::DiffuseFieldMask );
			 
	GeometryPtr pyramidPillarRoofGeo = GeometryPtr::dcast(pillarRoof->getCore());
	beginEditCP(pyramidPillarRoofGeo);
		pyramidPillarRoofGeo->setMaterial(pyramidPillarRoofMat);
	endEditCP(pyramidPillarRoofGeo);
	
	
	// sand

	cout << "--> parsing external object: sand.wrl" << endl;
	NodePtr external_sand = SceneFileHandler::the().read("external_objects/sand.wrl");
	
	// Transformation
	TransformPtr tsand = Transform::create();
	beginEditCP(tsand, Transform::MatrixFieldMask);
		m.setIdentity();
		m.setScale(0.3);
		m.setTranslate(1100,100, 2600);
		tsand->setMatrix(m);
	endEditCP(tsand, Transform::MatrixFieldMask);

	TransformPtr rsand = Transform::create();
	beginEditCP(rsand, Transform::MatrixFieldMask);
		m.setIdentity();
		//m.setRotate(Quaternion(Vec3f(0,1,0), M_PI/2));
		rsand->setMatrix(m);
	endEditCP(rsand, Transform::MatrixFieldMask);

	NodePtr external_sand_Rot = Node::create();
	beginEditCP(external_sand_Rot, Node::CoreFieldMask | Node::ChildrenFieldMask);
		external_sand_Rot->setCore(rsand);
		external_sand_Rot->addChild(external_sand);
	endEditCP(external_sand_Rot, Node::CoreFieldMask | Node::ChildrenFieldMask);

	NodePtr external_sand_Trans = Node::create();
	beginEditCP(external_sand_Trans, Node::CoreFieldMask | Node::ChildrenFieldMask);
		external_sand_Trans->setCore(tsand);
		external_sand_Trans->addChild(external_sand_Rot);
	endEditCP(external_sand_Trans, Node::CoreFieldMask | Node::ChildrenFieldMask);
	
	
	
	// Erstellen eines Knotens
	NodePtr holeTerasse = Node::create();
	beginEditCP(holeTerasse, Node::CoreFieldMask);
	{
		holeTerasse->setCore(Group::create());
		holeTerasse->addChild(terrasseTrans);
		
		holeTerasse->addChild(zaunMTrans);
		holeTerasse->addChild(zaunLTrans);
		holeTerasse->addChild(zaunRTrans);
		holeTerasse->addChild(zaunPfostenLTrans);
		holeTerasse->addChild(zaunPfostenRTrans);

		holeTerasse->addChild(external_sand_Trans);		

		holeTerasse->addChild(pyramidPillarLeftTrans);
		holeTerasse->addChild(pyramidPillarRightTrans);
		holeTerasse->addChild(pyramidPillarLeftFrontTrans);
		holeTerasse->addChild(pyramidPillarRightFrontTrans);
		holeTerasse->addChild(pillarPassTrans);
	}
	endEditCP  (holeTerasse, Node::CoreFieldMask);
	
	
	return holeTerasse;
}
